package gwt.immunology.client.view;

import static gwt.immunology.shared.GenericDtoKeys.BIRTHDAY;
import static gwt.immunology.shared.GenericDtoKeys.FIRST_NAME;
import static gwt.immunology.shared.GenericDtoKeys.GENDER;
import static gwt.immunology.shared.GenericDtoKeys.ID;
import static gwt.immunology.shared.GenericDtoKeys.LAST_NAME;
import static gwt.immunology.shared.GenericDtoKeys.MIDDLE_NAME;
import static gwt.immunology.shared.utils.ImmunologyUtils.DD_MM_YYYY;
import gwt.immunology.client.components.CustomBox;
import gwt.immunology.client.components.ViewEditPatientBox;
import gwt.immunology.client.i18n.ImmunologyI18N;
import gwt.immunology.client.resources.ImmunologyResources;
import gwt.immunology.shared.GenericDto;
import gwt.immunology.shared.ResultSetDto;
import gwt.immunology.shared.enums.GenderEnum;
import gwt.immunology.shared.utils.ImmunologyUtils;

import java.util.LinkedList;
import java.util.List;

import com.google.gwt.cell.client.ButtonCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;

public class AllPatientsViewImpl extends Composite implements AllPatientsView {
    private Presenter presenter;
    private PatientsDataProvider provider = new PatientsDataProvider();
    private ImmunologyI18N i18n = GWT.create(ImmunologyI18N.class);
    private ViewEditPatientBox patientWindow;

    private static AllPatientsViewImplUiBinder uiBinder = GWT.create(AllPatientsViewImplUiBinder.class);

    interface AllPatientsViewImplUiBinder extends UiBinder<Widget, AllPatientsViewImpl> {
    }

    private class PatientsDataProvider extends AsyncDataProvider<GenericDto> {
    	private List<GenericDto> currentPatients = new LinkedList<GenericDto>();
    
    	@Override
    	protected void onRangeChanged(HasData<GenericDto> display) {
    	    if (presenter != null) {
    	        presenter.getAllPatients();
    	    }
    	}
    
    	public void update(List<GenericDto> devices) {
    	    currentPatients.clear();
    	    currentPatients.addAll(devices);
    	    refresh();
    	}
    
    	public void refresh() {
    	    updateRowData(0, currentPatients);
    	    updateRowCount(currentPatients.size(), true);
    	}
    };

    public AllPatientsViewImpl() {
    	patientsTable = new CellTable<GenericDto>(15, ImmunologyResources.CELL_TABLE);
    
    	ListHandler<GenericDto> columnSortHandler = new ListHandler<GenericDto>(provider.currentPatients) {
    	    @Override
    	    public void onColumnSort(ColumnSortEvent event) {
    		super.onColumnSort(event);
    		provider.refresh();
    	    }
    	};
    	patientsTable.addColumnSortHandler(columnSortHandler);
    
    	// Init "ID" Column
    	TextColumn<GenericDto> idColumn = new TextColumn<GenericDto>() {
    	    @Override
    	    public String getValue(GenericDto object) {
    		return object.getString(ID);
    	    }
    	};
    	idColumn.setSortable(true);
    	columnSortHandler.setComparator(idColumn, new GenericDto.DefaultComparator(ID));
    	patientsTable.addColumn(idColumn, "ID");
    	patientsTable.setColumnWidth(idColumn, 9, Unit.PCT);
    
    	// Init "Last Name" Column
    	TextColumn<GenericDto> lastNameColumn = new TextColumn<GenericDto>() {
    	    @Override
    	    public String getValue(GenericDto object) {
    		return object.getString(LAST_NAME);
    	    }
    	};
    	lastNameColumn.setSortable(true);
    	columnSortHandler.setComparator(lastNameColumn, new GenericDto.DefaultComparator(LAST_NAME));
    	patientsTable.addColumn(lastNameColumn, i18n.tableLastName());
    	patientsTable.setColumnWidth(lastNameColumn, 18, Unit.PCT);
    
    	// Init "First Name" Column
    	TextColumn<GenericDto> firstNameColumn = new TextColumn<GenericDto>() {
    	    @Override
    	    public String getValue(GenericDto object) {
    		return object.getString(FIRST_NAME);
    	    }
    	};
    	firstNameColumn.setSortable(true);
    	columnSortHandler.setComparator(firstNameColumn, new GenericDto.DefaultComparator(FIRST_NAME));
    	patientsTable.addColumn(firstNameColumn, i18n.tableFirstName());
    	patientsTable.setColumnWidth(firstNameColumn, 17, Unit.PCT);
    
    	// Init "Middle Name" Column
    	TextColumn<GenericDto> middleNameColumn = new TextColumn<GenericDto>() {
    	    @Override
    	    public String getValue(GenericDto object) {
    		return object.getString(MIDDLE_NAME);
    	    }
    	};
    	middleNameColumn.setSortable(true);
    	columnSortHandler.setComparator(middleNameColumn, new GenericDto.DefaultComparator(MIDDLE_NAME));
    	patientsTable.addColumn(middleNameColumn, i18n.tableMiddleName());
    	patientsTable.setColumnWidth(middleNameColumn, 18, Unit.PCT);
    
    	// Init "Gender" Column
    	TextColumn<GenericDto> genderColumn = new TextColumn<GenericDto>() {
    	    @Override
    	    public String getValue(GenericDto object) {
    		String result = null;
    		GenderEnum genderEnum = GenderEnum.valueOf(object.getString(GENDER));
    		if (genderEnum == GenderEnum.MALE) {
    		    result = i18n.genderMale();
    		} else if (genderEnum == GenderEnum.FEMALE) {
    		    result = i18n.genderFemale();
    		} else {
    		    result = "";
    		}
    		return result;
    	    }
    	};
    	genderColumn.setSortable(true);
    	columnSortHandler.setComparator(genderColumn, new GenericDto.DefaultComparator(GENDER));
    	patientsTable.addColumn(genderColumn, i18n.tableGender());
    	patientsTable.setColumnWidth(genderColumn, 13, Unit.PCT);
    
    	// Init "Birthday" Column
    	TextColumn<GenericDto> birthdayColumn = new TextColumn<GenericDto>() {
    	    @Override
    	    public String getValue(GenericDto object) {
    		return ImmunologyUtils.convertDateToString(object.getDate(BIRTHDAY), DD_MM_YYYY);
    	    }
    	};
    	birthdayColumn.setSortable(true);
    	columnSortHandler.setComparator(birthdayColumn, new GenericDto.DefaultComparator(BIRTHDAY));
    	patientsTable.addColumn(birthdayColumn, i18n.tableBirthday());
    	patientsTable.setColumnWidth(birthdayColumn, 25, Unit.PCT);
    
    	// Init "Additional Info" Column
    	ButtonCell previewButton = new ButtonCell();
    	Column<GenericDto, String> preview = new Column<GenericDto, String>(previewButton) {
    	    public String getValue(GenericDto object) {
    		return ">>>";
    	    }
    	};
    	preview.setFieldUpdater(new FieldUpdater<GenericDto, String>() {
    	    @Override
    	    public void update(int index, GenericDto patient, String value) {
    	        patientWindow = new ViewEditPatientBox("View / Edit / Delete Patient", patient, presenter);
    	        patientWindow.show();
    	    }
    	});
    	patientsTable.addColumn(preview);
    
    	provider.addDataDisplay(patientsTable);
    	pager = new SimplePager();
    	pager.setDisplay(patientsTable);
    
    	initWidget(uiBinder.createAndBindUi(this));
    }

    @UiField public CustomBox customBox;
    @UiField public Label patientsNumber;
    @UiField public Label searchResultNumber;
    @UiField(provided = true) public CellTable patientsTable;
    @UiField(provided = true) public SimplePager pager;
    @UiField public HorizontalPanel searchResultPanel;
    @UiField public Button clearSearchButton;

    @UiHandler("clearSearchButton")
    void clearSearchButtonHandler(ClickEvent e) {
        this.presenter.getAllPatients();
    }

    @Override
    public void setPatients(ResultSetDto patients, Long patientsCount) {
    	boolean displayTable = patients.size() == 0 ? false : true;
    	patientsTable.setVisible(displayTable);
    	pager.setVisible(displayTable);
    	provider.update(patients);
    	ColumnSortEvent.fire(patientsTable, patientsTable.getColumnSortList());
    
    	if (patientsCount != null) {
    	    clearSearchButton.setVisible(true);
    	    searchResultPanel.setVisible(true);
    	    searchResultNumber.setText("" + patients.size());
    	    patientsNumber.setText("" + patientsCount);
    	} else {
    	    clearSearchButton.setVisible(false);
    	    searchResultPanel.setVisible(false);
    	    patientsNumber.setText("" + patients.size());
    	}
    }

    @Override
    public void hideViewEditPatientBox() {
        this.patientWindow.hide();
    }

    @Override
    public void setPresenter(Presenter presenter) {
        this.presenter = presenter;
    }

}
